package cn.z2huo.usercenter.authentication.app.aspect;

import cn.z2huo.usercenter.authentication.model.vo.login.test.UserLoginReqVO;
import cn.z2huo.usercenter.util.RedisKeyGenerateUtils;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;

import java.time.Duration;

/**
 * <p>固定窗口限流
 *
 * @author z2huo
 */
//@Aspect
//@Component
@RequiredArgsConstructor
//@Order(1)
public class FixedWindowLoginLimitAspect {

    private final RedissonClient redissonClient;

    private static final int LIMIT_COUNT = 5;

    private static final Duration LIMIT_TIME_DURATION = Duration.ofSeconds(60);

    @Pointcut("execution(* cn.z2huo.usercenter.authentication.app.controller.login.test.LoginLimitController.login(..)) && args(reqVO)")
    public void pointcut(UserLoginReqVO reqVO) {
    }

    @Before(value = "pointcut(reqVO)", argNames = "reqVO")
    public void before(UserLoginReqVO reqVO) {

        String redisKey = RedisKeyGenerateUtils.AUTHENTICATION_APP.generateMd5("user-login-fixed", reqVO.getUserCode());

        RAtomicLong atomicLong = redissonClient.getAtomicLong(redisKey);
        long count = atomicLong.getAndIncrement();

        if (count == 1) {
            // count == 1 之后，执行 expire 之前，程序异常终止了，那么这个 key 就没有失效时间
            atomicLong.expire(LIMIT_TIME_DURATION);
        }
        if (count >= LIMIT_COUNT) {
            throw new RuntimeException("限制时间内登陆次数过多，请稍后再试");
        }
    }

}
